package cn.stylefeng.guns.sys.core.util;

import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import javax.xml.soap.*;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

/**
 * 发送自定义soap报文（内嵌jsonString）获取返回报文工具类
 */
public class SoapUtil {
    //对接服务地址
    private String addressUrl="http://XXXXXXXX";


//    public SoapHepler(String addressUrl) {
//        if(addressUrl!=null&&!"".equals(addressUrl.trim())){
//            this.addressUrl = addressUrl;
//        }
//    }
    /**
     * 添加所需信息
     * @param bodyJsonStr  请求体json
     * @param svcname      服务名称
     * @param svccode      服务编码
     * @param svcver       服务版本
     * @param orisys       来源系统标识
     * @param trantime     交易发起时间
     * @param tranno       全局交易流水号
     * @param branchno     操作员机构代码op
     * @param userid       用户IDop
     * @param tokenid      口令或令牌op
     * @param signature    数字签名op
     * @param branchnoo    机构代码
     * @param destsys      目标系统标识
     * @return
     */
    public String sendSoapXml(String bodyJsonStr,
                              String svcname, String svccode,
                              String svcver,String orisys,
                              String trantime,String tranno,
                              String branchno,String userid,
                              String tokenid,String signature,
                              String branchnoo,String destsys) {
        String AUTH_PREFIX = "cl";
        String AUTH_NS = "http://www.e-chinalife.com/soa/";
        String XSD_NS = "http://www.w3.org/2001/XMLSchema";
        String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
        try {
            //实例化一个soap连接对象工厂
            SOAPConnectionFactory soapConnFactory = SOAPConnectionFactory.newInstance();
            //实例化一个连接对象
            SOAPConnection connection = soapConnFactory.createConnection();
            //实例化一个消息对象
            MessageFactory messageFactory = MessageFactory.newInstance();
            //实例化一个消息
            SOAPMessage message = messageFactory.createMessage();
            //获取消息中soap消息部分的句柄
            SOAPPart soapPart = message.getSOAPPart();
            //获取soap消息部分中的信封句柄
            SOAPEnvelope envelope = soapPart.getEnvelope();
            envelope.setPrefix("soapenv");
            envelope.removeNamespaceDeclaration("SOAP-ENV");
//            envelope.setAttribute("xmlns:xsd", XSD_NS);
            envelope.setAttribute("xmlns:xsi", XSI_NS);
            envelope.setAttribute("xmlns:soa", AUTH_NS);
            //获取信封中需要填写的请求报文部分的句柄
            //创建soap工厂
            SOAPFactory soapFactory = SOAPFactory.newInstance();
            //添加消息体以及json字符串
            SOAPBody body = envelope.getBody();
            body.setPrefix("soapenv");
            SOAPBodyElement bodyElement = body.addBodyElement(envelope.createName("execute", "soa", null));
            SOAPElement requestData = bodyElement.addChildElement("requestData","soa");
            requestData.addTextNode(judgeNull(bodyJsonStr));
            //添加信息头内容
            SOAPHeader header = envelope.getHeader();
            header.setPrefix("soapenv");
            SOAPElement wsHeaderElm = soapFactory.createElement("HEADER", AUTH_PREFIX, AUTH_NS);
            SOAPElement svcnameElm = soapFactory.createElement("SVCNAME");
            SOAPElement svccodeNameElm = soapFactory.createElement("SVCCODE");
            SOAPElement svcverElm = soapFactory.createElement("SVCVER");
            SOAPElement orisysElm = soapFactory.createElement("ORISYS");
            SOAPElement trantimeElm = soapFactory.createElement("TRANTIME");
            SOAPElement trannoElm = soapFactory.createElement("TRANNO");
            SOAPElement authElm = soapFactory.createElement("AUTH");
            SOAPElement securityElm = soapFactory.createElement("SECURITY");
            SOAPElement routeElm = soapFactory.createElement("ROUTE");
            SOAPElement branchnoElm = soapFactory.createElement("BRANCHNO");
            SOAPElement useridElm = soapFactory.createElement("USERID");
            SOAPElement tokenidElm = soapFactory.createElement("TOKENID");
            SOAPElement signatureElm = soapFactory.createElement("SIGNATURE");
            SOAPElement branchnooElm = soapFactory.createElement("BRANCHNO");
            SOAPElement destsysElm = soapFactory.createElement("DESTSYS");
            //为上述消息头标签添加节点文本值
            svcnameElm.addTextNode(judgeNull(svcname));
            svccodeNameElm.addTextNode(judgeNull(svccode));
            svcverElm.addTextNode(judgeNull(svcver));
            orisysElm.addTextNode(judgeNull(orisys));
            trantimeElm.addTextNode(judgeNull(trantime));
            trannoElm.addTextNode(judgeNull(tranno));
            branchnoElm.addTextNode(judgeNull(branchno));
            useridElm.addTextNode(judgeNull(userid));
            tokenidElm.addTextNode(judgeNull(tokenid));
            signatureElm.addTextNode(judgeNull(signature));
            branchnooElm.addTextNode(judgeNull(branchnoo));
            destsysElm.addTextNode(judgeNull(destsys));
            authElm.addChildElement(branchnoElm);
            authElm.addChildElement(useridElm);
            authElm.addChildElement(tokenidElm);
            securityElm.addChildElement(signatureElm);
            routeElm.addChildElement(branchnooElm);
            routeElm.addChildElement(destsysElm);
            wsHeaderElm.addChildElement(svcnameElm);
            wsHeaderElm.addChildElement(svccodeNameElm);
            wsHeaderElm.addChildElement(svcverElm);
            wsHeaderElm.addChildElement(orisysElm);
            wsHeaderElm.addChildElement(trantimeElm);
            wsHeaderElm.addChildElement(trannoElm);
            wsHeaderElm.addChildElement(authElm);
            wsHeaderElm.addChildElement(securityElm);
            wsHeaderElm.addChildElement(routeElm);
            header.addChildElement(wsHeaderElm);
            message.saveChanges();
            System.out.println("输出报文，如下：");
            message.writeTo(System.out);
            //发送信息
            SOAPMessage call = connection.call(message, addressUrl);
            TransformerFactory transformerFactory=TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            Source sourceContent = call.getSOAPPart().getContent();
            StreamResult result = new StreamResult(new ByteArrayOutputStream());
            transformer.transform(sourceContent,result);
            //获取返回报文
            String s = ((ByteArrayOutputStream) result.getOutputStream()).toString();
            System.out.println("返回报文,如下：");
            System.out.print( s);
            connection.close();
            return s;
        } catch (Exception e) {
            e.printStackTrace();
            //throw new BusException("返回报文失败  ,错误信息："+e);
        }
        return null;
    }
    /**添加上述节点文本是不能为null
     * 如果str为null 置为“”
     * @param str
     * @return
     */
    public static  String  judgeNull(String str){
        return (str==null)?"":str;
    }

    /**
     * <p>Description: 根据请求报文，请求服务地址获取 响应报文
     * @param requestSoap  请求报文
     * @param serviceAddress 响应报文
     * @param charSet 字符集
     * @param contentType  类型
     * @return  map封装的 服务器响应参数和返回报文.PS:statusCode :200正常响应。responseSoap：响应报文
     * <p>thinking: </p>
     * @author  liuy
     */
    public  static Map<String,Object> responseSoap(String requestSoap, String serviceAddress, String charSet, String contentType){
        String responseSoap="";
        Map<String,Object> resultmap=new HashMap<>();
        PostMethod postMethod = new PostMethod(serviceAddress);
        byte[] b = new byte[0];
        try {
            b = requestSoap.getBytes(charSet);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        InputStream is = new ByteArrayInputStream(b, 0, b.length);
        RequestEntity re = new InputStreamRequestEntity(is, b.length, contentType);
        postMethod.setRequestEntity(re);
        HttpClient httpClient = new HttpClient();
        int statusCode = 8;
        try {
            statusCode = httpClient.executeMethod(postMethod);
            resultmap.put("statusCode", statusCode);
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("执行http请求失败", e);
        }
        if (statusCode == 200) {
            try {
                responseSoap = postMethod.getResponseBodyAsString();
                resultmap.put("responseSoap", responseSoap);
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException("获取请求返回报文失败", e);
            }
        } else {
            throw new RuntimeException("请求失败：" + statusCode);

        }
        return resultmap;
    }
    public static  String sendHttpRequest(String ipAddress, int nPort, String  sRequest) throws UnsupportedEncodingException {
        String sResult="";
        OutputStream out = null;
        BufferedReader in =null;
        //如系统使用UTF-8编码，需将请求报文转码为GB18030
        String encoding="GB18030";
        //HTTP请求需将请求报文放在requestXm1参数发送
        String params="requestXml="+ URLEncoder.encode(sRequest,encoding);
        String path="http://"+ ipAddress+":"+ nPort;
        URL url;
        try {
            url = new URL(path);
            HttpURLConnection conn=(HttpURLConnection)url.openConnection();
            //设置连接超时时间
            conn.setConnectTimeout(10 *1000);
            //将 dooutput 标志设置为 true，指示应用程序要将数据写入 URL 连接
            conn.setDoOutput(true);
            //将 doInput 标志设置为 true，指示应用程序要从URL 连接读取数据
            conn.setDoInput(true);
            //设置HTTP请求报文头
            conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
            conn.setRequestProperty("Content-Length",String.valueOf(params.length()));
            conn.setRequestProperty("Connection","close");
            //发送请求报文数据
            out = conn.getOutputStream();
            out .write (params .getBytes(encoding));
            out.close ();
            //读取返回数据
            System.out.println("conn.getResponseCode():"+conn.getResponseCode());
            if (conn.getResponseCode() ==200){
                in = new BufferedReader(new InputStreamReader(conn.getInputStream(),encoding));
            } else {
                in =new BufferedReader(new InputStreamReader(conn.getErrorStream(),encoding));
            }

            String sLine;
            StringBuffer sb = new StringBuffer();
            while ((sLine = in.readLine())!=null) {
                sb.append(sLine);
            }
            sResult =sb.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if(in!=null){
                    in.close();
                }if(out!=null){
                    out.close();
                }
            }catch (IOException e) {
                e.printStackTrace();
            }
        }
        return  sResult;
    }
}
